/*
    Geocache: some utilities for managing and visualizing geocache information
    Copyright (C) 2008  Gary Jackson

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * MessageCollection.java
 */

package com.thegbomb.common;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import javax.mail.search.SearchTerm;
import org.apache.log4j.Logger;

/**
 *
 * @author Gary Jackson
 */
public class MessageCollection implements Collection<Message> {
    static private Logger logger = Logger.getLogger(MessageCollection.class);
    private Collection<Message> internal;
    private Store store;
    
    private Session session;
    private URLName urln;
    private SearchTerm term;
    
    /**
     * Creates a new instance of MessageCollection
     */
    public MessageCollection(Session session, URLName urln, SearchTerm term) throws MessagingException {
        this.internal = new LinkedList<Message>();
        this.store = session.getStore(urln);
        
        boolean done = false;
        try {
            logger.info("connecting to the store specified by the session");
            store.connect();
            Folder inbox = store.getFolder("INBOX");
            inbox.open(Folder.READ_ONLY);
            
            logger.info("searching for messages");
            Message[] messages = inbox.search(term);
            
            FetchProfile profile = new FetchProfile();
            profile.add(FetchProfile.Item.ENVELOPE);
            
            inbox.fetch(messages, profile);
            
            logger.info("fetched " + messages.length + " messages");
            
            DateFormat df = DateFormat.getDateTimeInstance();
            for (int i = 0; i < messages.length; i++) {
                String from = decodeText(messages[i].getFrom()[0].toString());
                InternetAddress ia = new InternetAddress(from);
                
                logger.info("messages["+i+"]: from: " + ia.getPersonal() + " <" + ia.getAddress() + ">");
                logger.info("messages["+i+"]: subject: " + messages[i].getSubject());
                logger.info("messages["+i+"]: date: " + df.format(messages[i].getSentDate()));
                
                this.internal.add(messages[i]);
            }
            
            done = true;
        } finally {
            if (!done)
                try {store.close();} catch (MessagingException e) { /* Ignore */ }
        }
    }
    
    private String decodeText(String text) {
        if (text == null)
            return null;
        
        try {
            if (text.startsWith("=?GB") || text.startsWith("=?gb"))
                text = MimeUtility.decodeText(text);
            else
                text = new String(text.getBytes("ISO8859_1"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        
        return text;
    }
    
    
    public void close() throws MessagingException {
        this.store.close();
    }
    
    public int size() {
        return internal.size();
    }
    
    public boolean isEmpty() {
        return internal.isEmpty();
    }
    
    public boolean contains(Object o) {
        return internal.contains(o);
    }
    
    public Iterator<Message> iterator() {
        return internal.iterator();
    }
    
    public Object[] toArray() {
        return internal.toArray();
    }
    
    public <T> T[] toArray(T[] t) {
        return internal.toArray(t);
    }
    
    public boolean add(Message m) {
        throw new UnsupportedOperationException("collection is read-only");
    }
    
    public boolean remove(Object o) {
        throw new UnsupportedOperationException("collection is read-only");
    }
    
    public boolean containsAll(Collection<?> c) {
        return internal.containsAll(c);
    }
    
    public boolean addAll(Collection<? extends Message> c) {
        throw new UnsupportedOperationException("collection is read-only");
    }
    
    public boolean removeAll(Collection<?> c) {
        throw new UnsupportedOperationException("collection is read-only");
    }
    
    public boolean retainAll(Collection<?> c) {
        throw new UnsupportedOperationException("collection is read-only");
    }
    
    public void clear() {
        throw new UnsupportedOperationException("collection is read-only");
    }
}
